#ifndef INTERP_PRIV_H
#define INTERP_PRIV_H

#define STRING_DELIM '"'
#define COMMENT_DELIM ';'

typedef enum TokenType
{
	TK_NONE, TK_EOI /* END OF INPUT */, TK_EOL,
	TK_SPACE, TK_COMMENT, TK_OPEN_PAREN, TK_CLOSE_PAREN,
	TK_STRING, TK_SYMBOL, TK_QUOTE
}
TokenType;

/* typedef struct BufUse BufUse; */
typedef struct Lexer Lexer;
typedef struct Token Token;
typedef struct SyntaxTree SyntaxTree;

/*
struct BufUse
{
	unsigned in_use : 1;
	signed priority: 7;
};
*/

struct Lexer
{
	int col;
	int line;
	int char_abs;
	
	int cur_tok_start_col;
	int cur_tok_start_line;
	int cur_tok_start_char_abs;

	int string; /* whether presently reading a string */
	int comment; /* whether presently reading a comment */

	char *outbuf;
	char *outbuf_end;
	/* int outbuf_mem; */
	/* int outbuf_len; */

	char *inbuf;
	char *inbuf_cur;
	char *inbuf_start;
	char *inbuf_end; /* char after valid char */
	/* int inbuf_mem; */
	/* int inbuf_len; */

/*
	FILE **files;
	/=* int files_mem; *=/
	int files_len;
	BufUse *file_use;

	char **filenames;
	/=* int filenames_mem; *=/
	int filenames_len;
*/
};

struct Token
{
	char *tok;
	int tok_len;
	TokenType ttype;
	/*
	 * If token can be converted into an Object,
	 * store the pointer here temporarily.
	 * If not converted, will be NULL.
	 */
	Object *result;
	/* No. of chars on line */
	int start_col;
	int end_col;
	/* No. of chars in file */
	int start_char_abs;
	int end_char_abs;
	/* No. of lines in file */
	int start_line;
	int end_line;
};

struct SyntaxTree
{
	Object *top; /* top-level pair/list for code syntax tree */
	Object *last; /* last object inserted; always points to part of the tree */
	Object *next; /* temp container for next object to insert */
};

static void Lexer_init(void);
static Lexer *Lexer_new(void);
/*
static int Lexer_feedFilePtr(Lexer *, FILE *);
static int Lexer_feedFileName(Lexer *, char *);
*/
static void Lexer_feedChars(Lexer *, char *, int); /* append chars to end of stream */
/* static void Lexer_push(Lexer *, char *, int); */ /* append chars to front of stream */
/* static int Lexer_hasNext(Lexer *); */ /* made into macro */
static Token *Lexer_next(Lexer *);

/* Sub-functions */
static int lexer_readChar(Lexer *);

#define lexer_hasNext(l) ((l)->inbuf_start < (l)->inbuf_end)
#define lexer_hasNextNotNull(l) ((l) && ((l)->inbuf_start < (l)->inbuf_end))
#define lexer_outBufferAppend(l, c) (*(l)->outbuf_end++ = (c))

#endif /* !INTERP_PRIV_H */
